#include "VxIrrLib.h"
/*
//------------------------------------------------------------------------------
//=== constructor ===//
IrrPhysAnimator::IrrPhysAnimator()
{
}
//------------------------------------------------------------------------------
//=== destructor ===//
IrrPhysAnimator::~IrrPhysAnimator()
{
	NodePhysShutdown();
}

//------------------------------------------------------------------------------
//! initialize
void IrrPhysAnimator::NodePhysStartup(	IrrPhysWorld *			poPhysWorld,
										irr::scene::ISceneNode* poSceneNode,
										IrrPhysGeomParams	*	poGeomParams,
										IrrPhysImpulseParams *	poImpulseParams )
{
	this->m_poPhysWorld		= poPhysWorld;
	this->m_poDynamicsWorld	= poPhysWorld->m_poDynamicsWorld;
	this->m_poSceneNode		= poSceneNode;

	memcpy( &this->m_oImpulseParams, poImpulseParams );
	m_poRigidBody = NULL;
	m_poMotionState = NULL;
	m_poCollisionShape = NULL;



	irr::core::aabbox3d<irr::f32> oBBox;
	irr::core::vector3df v3fScale = poSceneNode->getScale();

	// if auto calculate then get params from scene node
	if( poGeomParams->m_bAutoCalculate )
	{
		if( irr::scene::ESNT_ANIMATED_MESH == poSceneNode->getType() )
		{
			if( pSceneNode->getBoundingBox().isEmpty()) 
			{
				IrrPhysRepairBoundingBox( (irr::scene::IAnimatedMeshSceneNode*)poSceneNode );
			}
		}
		oBBox = poSceneNode->getBoundingBox();
		irr::core::vector3df v3fBBoxExtent = oBBox.getExtent() ;

		poGeomParams->BoxParams.X = v3fBBoxExtent.X * v3fScale.X * 0.5f;
		poGeomParams->BoxParams.Y = v3fBBoxExtent.Y * v3fScale.Y * 0.5f;
		poGeomParams->BoxParams.Z = v3fBBoxExtent.Z * v3fScale.Z * 0.5f;
		poGeomParams->SphereParams.m_f32Radius = IrrPhysGetMaxRadius( oBBox, v3fScale ) * 0.5f;
	}


	// prepare collision shape
	btCollisionShape* collisionShape = NULL;
	switch( poGeomParams->m_ePhysGeomType )
	{
	case CBPAGT_SPHERE:
		{
			collisionShape = new btSphereShape(pGeom->sphere.radius);
		} break;

	case CBPAGT_BOX:
		{
			collisionShape = new btBoxShape(btVector3(pGeom->box.X, pGeom->box.Y, pGeom->box.Z));
		} break;

	case CBPAGT_CYLINDER:
		{
			collisionShape = new btCylinderShape(btVector3(pGeom->box.X, pGeom->box.Y, pGeom->box.Z));
		} break;

	case CBPAGT_CAPSULE:
		{
			if (pGeom->AutoCalculate)       {
				box=pSceneNode->getTransformedBoundingBox();
				collisionShape = new btCapsuleShape((box.MaxEdge.X - box.getCenter().X)*scaling.X  ,//radio
					(box.MaxEdge.Y - box.MinEdge.Y)*scaling.Y*0.5); //altura
			}
			else collisionShape = new btCapsuleShape(pGeom->box.X, pGeom->box.Y*2);

		} break;

	case CBPAGT_CONE:
		{
			collisionShape = new btConeShape(pGeom->box.X, pGeom->box.Y*2);
		} break;

	case CBPAGT_STATIC_PLANE:
		{
			collisionShape = new btStaticPlaneShape(btVector3(pGeom->box.X, pGeom->box.Y, pGeom->box.Z),1);
		} break;

	case CBPAGT_CONVEX_MESH:
		{
			btTriangleMesh* triangleMesh =
				ConvertIrrMeshToBulletTriangleMesh(pGeom->mesh.irrMesh, scaling);
			//btTriangleIndexVertexArray* triangleMesh =
			//  ConvertIrrMeshToBulletTriangleArray(pGeom->mesh.irrMesh, scaling);
			collisionShape = new btConvexTriangleMeshShape(triangleMesh);

			//collisionShape = ConvertIrrMeshToBulletConvexHullShape(pGeom->mesh.irrMesh);
		} break;

	case CBPAGT_CONCAVE_MESH:
		{
			btTriangleMesh* triangleMesh;
			bool useQuantizedAabbCompression = true;

			if (pSceneNode->getType() == ESNT_TERRAIN )
				triangleMesh =ConvertTerrainToBulletTriangleMesh((scene::ITerrainSceneNode*)pSceneNode,scaling);
			else
				triangleMesh =ConvertIrrMeshToBulletTriangleMesh(pGeom->mesh.irrMesh, scaling);

			collisionShape = new btBvhTriangleMeshShape(triangleMesh, useQuantizedAabbCompression);
			//collisionShape = new btConvexHullShape();
		} break;

	case CBPAGT_CONCAVE_GIMPACT_MESH:
		{
			btTriangleMesh* triangleMesh =
				ConvertIrrMeshToBulletTriangleMesh(pGeom->mesh.irrMesh, scaling);
			//btTriangleIndexVertexArray* triangleMesh = ConvertIrrMeshToBulletTriangleArray(pGeom->mesh.irrMesh);
			btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(triangleMesh);
			gimpactShape->updateBound();
			collisionShape = gimpactShape;
		} break;

	default:
		// unknown type
		break;
	}
	if (collisionShape == NULL)
	{
		return NULL;
	}
	this->m_poCollisionShape = collisionShape;


  //rigidbody is dynamic if and only if mass is non zero, otherwise static
  bool isDynamic = (physicsParams.mass != 0.0f);

  // calculate inertia vector
  btVector3 localInertia(0,0,0);
  if (isDynamic)
    collisionShape->calculateLocalInertia(physicsParams.mass, localInertia);

  //collisionShape->setUserPointer((void *)sceneNode);
  //printf("set pointer %d \n", sceneNode);

  // calculate value for ccdThreshold
  core::aabbox3d<f32> box = sceneNode->getBoundingBox();
  core::vector3df ext = box.getExtent();
  f32 ret=0;
  if (ext.X>ret) ret=ext.X;
  if (ext.Y>ret) ret=ext.Y;
  if (ext.Z>ret) ret=ext.Z;
  physicsParams.ccdThreshold = ret/2;

  // evaluate start transform in terms of btTransform
  // and set offset of center of mass
  btTransform	startTransform, centerOfMassOffset;
  GetNodeTransform(sceneNode, startTransform);
  centerOfMassOffset.setIdentity();
  centerOfMassOffset.setOrigin(btVector3(physicsParams.centerOfMassOffset.X,
    physicsParams.centerOfMassOffset.Y, physicsParams.centerOfMassOffset.Z));

  //using motionstate is recommended, it provides interpolation capabilities,
  //and only synchronizes 'active' objects
  motionState = new btDefaultMotionState(startTransform, centerOfMassOffset);
  // create body
  btRigidBody::btRigidBodyConstructionInfo rigidBodyInfo(physicsParams.mass,
    motionState,
    collisionShape,
    localInertia);
  //rigidBodyInfo.m_angularDamping=  physicsParams.angularDamping;
  //rigidBodyInfo.m_linearDamping=  physicsParams.linearDamping;
  //rigidBodyInfo.m_restitution=  physicsParams.restitution;
  //rigidBodyInfo.m_friction=  physicsParams.friction;
  rigidBody = new btRigidBody(rigidBodyInfo);
  if(!isDynamic)
    rigidBody->setCollisionFlags( rigidBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);


  rigidBody->setUserPointer((void *)this);


  // add body to the world
  if (physicsParams.FilterEnabled)
    dynamicWorld->addRigidBody(rigidBody,physicsParams.FilterGroup,physicsParams.FilterMask );
  else
    dynamicWorld->addRigidBody(rigidBody);


  // Only do CCD if  motion in one timestep (1.f/60.f) exceeds half dims
  rigidBody->setCcdMotionThreshold(physicsParams.ccdThreshold);
  //Experimental: better estimation of CCD Time of Impact:
  rigidBody->setCcdSweptSphereRadius(0.2*physicsParams.ccdThreshold);
}

//------------------------------------------------------------------------------
//! shutdown
void IrrPhysAnimator::NodePhysShutdown( void )
{
  if (dynamicWorld)
    dynamicWorld->removeRigidBody(rigidBody);

  SAFE_DELETE(motionState);
  SAFE_DELETE(rigidBody);
}

//------------------------------------------------------------------------------
//! animates a scene node
void IrrPhysAnimator::animateNode( irr::scene::ISceneNode* node, irr::u32 timeMs)
{
}

//------------------------------------------------------------------------------
//! Writes attributes of the scene node animator.
void IrrPhysAnimator::serializeAttributes(irr::io::IAttributes* out, irr::io::SAttributeReadWriteOptions* options )
{
}

//------------------------------------------------------------------------------
//! Reads attributes of the scene node animator.
void IrrPhysAnimator::deserializeAttributes(irr::io::IAttributes* in, irr::io::SAttributeReadWriteOptions* options )
{
}


//------------------------------------------------------------------------------
//! get position
irr::core::vector3df IrrPhysAnimator::getPosition() const
{
	btVector3 p = rigidBody->getCenterOfMassPosition();
	return irr::core::vector3df(p.getX(), p.getY(), p.getZ());
}
//------------------------------------------------------------------------------
//! set position
void IrrPhysAnimator::setPosition(const irr::core::vector3df& v3fPos ) const
{
	vx_assert(rigidBody != NULL);

	btTransform t = rigidBody->getWorldTransform();
	btVector3 btv(v.X, v.Y, v.Z);
	t.setOrigin(btv);
	rigidBody->setWorldTransform(t);
}
//------------------------------------------------------------------------------
//! get rotation
irr::core::vector3df IrrPhysAnimator::getRotation() const
{
  core::vector3df rot;
  btQuaternion btq=rigidBody->getOrientation();
  QuaternionToEulerXYZ(btq, rot);
  rot *= BPU_360_PI2;
  return rot;
}
//------------------------------------------------------------------------------
//! set rotation
void IrrPhysAnimator::setRotation(const irr::core::vector3df& v3fRot ) const
{
  btTransform t = rigidBody->getWorldTransform();
  btQuaternion btq;
  EulerXYZToQuaternion(v, btq);
  t.setRotation(btq);
  rigidBody->setWorldTransform(t);
}
//------------------------------------------------------------------------------
irr::core::vector3df IrrPhysAnimator::getLinearVelocity() const
{
  if (physicsParams.mass == 0.0f)
    return core::vector3df(0,0,0);
  btVector3 btV = rigidBody->getLinearVelocity();
  return core::vector3df(btV.getX(), btV.getY(), btV.getZ());
}
//------------------------------------------------------------------------------
void IrrPhysAnimator::setLinearVelocity(const irr::core::vector3df& vel ) const
{
  //bullet hangs if attempt to set lin. or ang. velocity on static object
  if (physicsParams.mass != 0.0f)
  {
    rigidBody->setLinearVelocity(btVector3(vel.X, vel.Y, vel.Z));
  }
  //note - apparently, need to use motion state on kinematic objects, and rigid body functions
  // on dynamic rigid bodies to change pos / rot etc.
}
//------------------------------------------------------------------------------
irr::core::vector3df IrrPhysAnimator::getAngularVelocity() const
{
  if (physicsParams.mass == 0.0f)
    return core::vector3df(0,0,0);

  btVector3 btV = rigidBody->getAngularVelocity();
  return core::vector3df(btV.getX(), btV.getY(), btV.getZ());
}
//------------------------------------------------------------------------------
void IrrPhysAnimator::setAngularVelocity(const irr::core::vector3df& vel ) const
{
  //bullet hangs if attempt to set lin. or ang. velocity on static object
  if (physicsParams.mass != 0.0f)
  {
    rigidBody->setAngularVelocity(btVector3(vel.X, vel.Y, vel.Z));
  }
}

//------------------------------------------------------------------------------
void IrrPhysAnimator::applyImpulse(	const irr::core::vector3df& impulse,
									const irr::core::vector3df& rel_pos ) const
{

  rigidBody->applyImpulse(btVector3(force.X, force.Y, force.Z),
    btVector3(rel_pos.X, rel_pos.Y, rel_pos.Z));
  rigidBody->activate();
}

//------------------------------------------------------------------------------
void IrrPhysAnimator::applyForce(	const irr::core::vector3df& force,
									const irr::core::vector3df& rel_pos ) const
{
  rigidBody->applyForce(btVector3(force.X, force.Y, force.Z),
    btVector3(rel_pos.X, rel_pos.Y, rel_pos.Z));
  rigidBody->activate();
}
//------------------------------------------------------------------------------
void IrrPhysAnimator::zeroForces()
{
  rigidBody->setLinearVelocity(btVector3(0,0,0));
  rigidBody->setAngularVelocity(btVector3(0,0,0));
}
//------------------------------------------------------------------------------
void IrrPhysAnimator::setActivationState(bool active)
{
  rigidBody->setActivationState((active) ? 1 : 0);
}
//------------------------------------------------------------------------------
void IrrPhysAnimator::activate(bool force = false)
{
  rigidBody->activate(force);
}
*/